<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>从python到Numpy | 小熊的技术文档</title>
    <meta name="generator" content="VuePress 1.8.2">
    <link rel="icon" href="/fav.ico">
    <link rel="stylesheet" href="/css/katex.min.css">
    <link rel="stylesheet" href="/css/github-markdown.min.css">
    <meta name="description" content="衣带渐宽终不悔，为伊消得人憔悴">
    
    <link rel="preload" href="/assets/css/0.styles.e6449353.css" as="style"><link rel="preload" href="/assets/js/app.9e067b79.js" as="script"><link rel="preload" href="/assets/js/2.983eb755.js" as="script"><link rel="preload" href="/assets/js/13.de8b1ace.js" as="script"><link rel="prefetch" href="/assets/js/10.79548333.js"><link rel="prefetch" href="/assets/js/11.31600f80.js"><link rel="prefetch" href="/assets/js/12.62bd3528.js"><link rel="prefetch" href="/assets/js/14.f5db1e75.js"><link rel="prefetch" href="/assets/js/15.bf827d4d.js"><link rel="prefetch" href="/assets/js/16.cc9a1a73.js"><link rel="prefetch" href="/assets/js/17.2cfaefeb.js"><link rel="prefetch" href="/assets/js/18.3af7782b.js"><link rel="prefetch" href="/assets/js/19.639f7e7b.js"><link rel="prefetch" href="/assets/js/20.dc862f59.js"><link rel="prefetch" href="/assets/js/21.916e1685.js"><link rel="prefetch" href="/assets/js/22.d7a955f4.js"><link rel="prefetch" href="/assets/js/23.078391ef.js"><link rel="prefetch" href="/assets/js/24.bb460a5a.js"><link rel="prefetch" href="/assets/js/25.d69f2326.js"><link rel="prefetch" href="/assets/js/26.6da7ea48.js"><link rel="prefetch" href="/assets/js/27.82e23d91.js"><link rel="prefetch" href="/assets/js/28.9073bbec.js"><link rel="prefetch" href="/assets/js/29.639259a4.js"><link rel="prefetch" href="/assets/js/3.e594e5b2.js"><link rel="prefetch" href="/assets/js/30.b49c622d.js"><link rel="prefetch" href="/assets/js/31.92f6c8b3.js"><link rel="prefetch" href="/assets/js/32.42419088.js"><link rel="prefetch" href="/assets/js/33.c82e2ab8.js"><link rel="prefetch" href="/assets/js/34.381de37e.js"><link rel="prefetch" href="/assets/js/35.5e86d478.js"><link rel="prefetch" href="/assets/js/36.31f218ce.js"><link rel="prefetch" href="/assets/js/37.0d287b3f.js"><link rel="prefetch" href="/assets/js/38.1324cf44.js"><link rel="prefetch" href="/assets/js/39.de6bdb51.js"><link rel="prefetch" href="/assets/js/4.440c4dd9.js"><link rel="prefetch" href="/assets/js/40.a22c9c27.js"><link rel="prefetch" href="/assets/js/41.4637d617.js"><link rel="prefetch" href="/assets/js/42.db815e2b.js"><link rel="prefetch" href="/assets/js/43.f0955a92.js"><link rel="prefetch" href="/assets/js/44.7d5faddf.js"><link rel="prefetch" href="/assets/js/45.a88ffc33.js"><link rel="prefetch" href="/assets/js/46.883caa71.js"><link rel="prefetch" href="/assets/js/47.6f2cfd60.js"><link rel="prefetch" href="/assets/js/48.ea25654e.js"><link rel="prefetch" href="/assets/js/49.f38c23a0.js"><link rel="prefetch" href="/assets/js/5.e8844f36.js"><link rel="prefetch" href="/assets/js/50.e03dd8e9.js"><link rel="prefetch" href="/assets/js/51.f6160d52.js"><link rel="prefetch" href="/assets/js/52.4daa8322.js"><link rel="prefetch" href="/assets/js/53.b30992e9.js"><link rel="prefetch" href="/assets/js/54.209f17e1.js"><link rel="prefetch" href="/assets/js/55.4f1dd95b.js"><link rel="prefetch" href="/assets/js/56.147ea3e8.js"><link rel="prefetch" href="/assets/js/57.5823e0e2.js"><link rel="prefetch" href="/assets/js/58.772320f9.js"><link rel="prefetch" href="/assets/js/59.5ab55a80.js"><link rel="prefetch" href="/assets/js/6.54e1cc95.js"><link rel="prefetch" href="/assets/js/60.b47b75bb.js"><link rel="prefetch" href="/assets/js/61.0cd5a012.js"><link rel="prefetch" href="/assets/js/62.35eb5453.js"><link rel="prefetch" href="/assets/js/63.d31f2118.js"><link rel="prefetch" href="/assets/js/64.03d35d7c.js"><link rel="prefetch" href="/assets/js/65.8bdc633f.js"><link rel="prefetch" href="/assets/js/66.dbbe8867.js"><link rel="prefetch" href="/assets/js/67.228613b5.js"><link rel="prefetch" href="/assets/js/68.d10a2687.js"><link rel="prefetch" href="/assets/js/69.7903847f.js"><link rel="prefetch" href="/assets/js/7.f5ab00eb.js"><link rel="prefetch" href="/assets/js/70.11ee4e27.js"><link rel="prefetch" href="/assets/js/8.95b39934.js"><link rel="prefetch" href="/assets/js/9.26cfd48c.js">
    <link rel="stylesheet" href="/assets/css/0.styles.e6449353.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">小熊的技术文档</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/front-end/" class="nav-link">
  🎨前端
</a></div><div class="nav-item"><a href="/back-end/" class="nav-link router-link-active">
  💻后端
</a></div><div class="nav-item"><a href="/practice/" class="nav-link">
  🚀实战
</a></div><div class="nav-item"><a href="/office/" class="nav-link">
  🏢办公
</a></div><div class="nav-item"><a href="/general/" class="nav-link">
  🍓通用
</a></div><div class="nav-item"><a href="/paper/" class="nav-link">
  🐸论文
</a></div><div class="nav-item"><a href="/general/fast.html" class="nav-link">
  ⚡快速笔记
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="🦉近期重点" class="dropdown-title"><span class="title">🦉近期重点</span> <span class="arrow down"></span></button> <button type="button" aria-label="🦉近期重点" class="mobile-dropdown-title"><span class="title">🦉近期重点</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/back-end/python.html" class="nav-link">
  🐇python常用模块
</a></li><li class="dropdown-item"><!----> <a href="/practice/zrender.html" class="nav-link">
  🌹zrender源码解析
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="⭐️资源" class="dropdown-title"><span class="title">⭐️资源</span> <span class="arrow down"></span></button> <button type="button" aria-label="⭐️资源" class="mobile-dropdown-title"><span class="title">⭐️资源</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://www.birdiesearch.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  小鸟搜索
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://salttiger.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  每天一本编程书
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://gitee.com/docmirror/dev-sidecar" target="_blank" rel="noopener noreferrer" class="nav-link external">
  开发者边车
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/front-end/" class="nav-link">
  🎨前端
</a></div><div class="nav-item"><a href="/back-end/" class="nav-link router-link-active">
  💻后端
</a></div><div class="nav-item"><a href="/practice/" class="nav-link">
  🚀实战
</a></div><div class="nav-item"><a href="/office/" class="nav-link">
  🏢办公
</a></div><div class="nav-item"><a href="/general/" class="nav-link">
  🍓通用
</a></div><div class="nav-item"><a href="/paper/" class="nav-link">
  🐸论文
</a></div><div class="nav-item"><a href="/general/fast.html" class="nav-link">
  ⚡快速笔记
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="🦉近期重点" class="dropdown-title"><span class="title">🦉近期重点</span> <span class="arrow down"></span></button> <button type="button" aria-label="🦉近期重点" class="mobile-dropdown-title"><span class="title">🦉近期重点</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/back-end/python.html" class="nav-link">
  🐇python常用模块
</a></li><li class="dropdown-item"><!----> <a href="/practice/zrender.html" class="nav-link">
  🌹zrender源码解析
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="⭐️资源" class="dropdown-title"><span class="title">⭐️资源</span> <span class="arrow down"></span></button> <button type="button" aria-label="⭐️资源" class="mobile-dropdown-title"><span class="title">⭐️资源</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://www.birdiesearch.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  小鸟搜索
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://salttiger.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  每天一本编程书
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://gitee.com/docmirror/dev-sidecar" target="_blank" rel="noopener noreferrer" class="nav-link external">
  开发者边车
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><a href="/back-end/daily.html" class="sidebar-link">每日冷知识</a></li><li><a href="/back-end/python.html" class="sidebar-link">Python 常用操作笔记</a></li><li><a href="/back-end/python-projects.html" class="sidebar-link">小python项目</a></li><li><a href="/back-end/koa2.html" class="sidebar-link">使用 koa2 开发服务端</a></li><li><a href="/back-end/numpy.html" aria-current="page" class="active sidebar-link">从python到Numpy</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/back-end/numpy.html#引言" class="sidebar-link">引言</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/back-end/numpy.html#简单例子" class="sidebar-link">简单例子</a></li><li class="sidebar-sub-header"><a href="/back-end/numpy.html#可读性vs速度" class="sidebar-link">可读性vs速度</a></li></ul></li><li class="sidebar-sub-header"><a href="/back-end/numpy.html#数列-array-的剖析" class="sidebar-link">数列（array）的剖析</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/back-end/numpy.html#介绍" class="sidebar-link">介绍</a></li></ul></li></ul></li><li><a href="/back-end/linux.html" class="sidebar-link">linux核心技能</a></li><li><a href="/back-end/docker.html" class="sidebar-link">Docker实战</a></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="从python到numpy"><a href="#从python到numpy" class="header-anchor">#</a> 从python到Numpy</h1> <h2 id="引言"><a href="#引言" class="header-anchor">#</a> 引言</h2> <h3 id="简单例子"><a href="#简单例子" class="header-anchor">#</a> 简单例子</h3> <p>Numpy是关于向量化的，如果您熟悉Python，这是您将面临的主要困难，因为您需要改变您的思维方式，您的新朋友（包括其他人）被命名为“vectors”、“arrays”、“views”或“ufuncs”。</p> <p>让我们举一个非常简单的例子，随机游走（random walk）。一种可能的面向对象方法是定义一个<code>RandomWalker</code>类并编写一个<code>walk</code>方法，该方法将在每个（random）步骤之后返回当前位置。很好，很可读，但很慢：</p> <h4 id="面向对象方法"><a href="#面向对象方法" class="header-anchor">#</a> 面向对象方法</h4> <div class="language-python extra-class"><pre class="language-python"><code><span class="token keyword">class</span> <span class="token class-name">RandomWalker</span><span class="token punctuation">:</span>
    <span class="token keyword">def</span> <span class="token function">__init__</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        self<span class="token punctuation">.</span>position <span class="token operator">=</span> <span class="token number">0</span>

    <span class="token keyword">def</span> <span class="token function">walk</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> n<span class="token punctuation">)</span><span class="token punctuation">:</span>
        self<span class="token punctuation">.</span>position <span class="token operator">=</span> <span class="token number">0</span>
        <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">:</span>
            <span class="token keyword">yield</span> self<span class="token punctuation">.</span>position
            self<span class="token punctuation">.</span>position <span class="token operator">+=</span> <span class="token number">2</span><span class="token operator">*</span>random<span class="token punctuation">.</span>randint<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span>

walker <span class="token operator">=</span> RandomWalker<span class="token punctuation">(</span><span class="token punctuation">)</span>
walk <span class="token operator">=</span> <span class="token punctuation">[</span>position <span class="token keyword">for</span> position <span class="token keyword">in</span> walker<span class="token punctuation">.</span>walk<span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">]</span>
</code></pre></div><p>基准测试告诉我们。</p> <div class="language-batch extra-class"><pre class="language-batch"><code>&gt;&gt;&gt; from tools import timeit
&gt;&gt;&gt; walker = RandomWalker<span class="token punctuation">(</span><span class="token punctuation">)</span>
&gt;&gt;&gt; timeit<span class="token punctuation">(</span>&quot;[position for position in walker.walk<span class="token punctuation">(</span><span class="token command"><span class="token keyword">n</span>=<span class="token number">10000</span></span><span class="token punctuation">)</span>]&quot;, globals<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token command"><span class="token keyword">10</span> loops, best of <span class="token number">3</span>: <span class="token number">15</span>.<span class="token number">7</span> msec per loop</span>
</code></pre></div><h4 id="程序方法"><a href="#程序方法" class="header-anchor">#</a> 程序方法</h4> <p>对于这样一个简单的问题，我们可能可以保存类定义，只关注walk方法，该方法在每个随机步骤之后计算连续的位置。</p> <div class="language-python extra-class"><pre class="language-python"><code><span class="token keyword">def</span> <span class="token function">random_walk</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">:</span>
    position <span class="token operator">=</span> <span class="token number">0</span>
    walk <span class="token operator">=</span> <span class="token punctuation">[</span>position<span class="token punctuation">]</span>
    <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">:</span>
        position <span class="token operator">+=</span> <span class="token number">2</span><span class="token operator">*</span>random<span class="token punctuation">.</span>randint<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token number">1</span>
        walk<span class="token punctuation">.</span>append<span class="token punctuation">(</span>position<span class="token punctuation">)</span>
    <span class="token keyword">return</span> walk

walk <span class="token operator">=</span> random_walk<span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span>
</code></pre></div><p>这个新方法节省了一些CPU周期，但没有那么多，因为这个函数与面向对象方法中的函数几乎相同，而且我们节省的几个周期可能来自Python面向对象的内部机制。</p> <div class="language-batch extra-class"><pre class="language-batch"><code>&gt;&gt;&gt; from tools import timeit
&gt;&gt;&gt; timeit<span class="token punctuation">(</span>&quot;random_walk<span class="token punctuation">(</span><span class="token command"><span class="token keyword">n</span>=<span class="token number">10000</span></span><span class="token punctuation">)</span>&quot;, globals<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token command"><span class="token keyword">10</span> loops, best of <span class="token number">3</span>: <span class="token number">15</span>.<span class="token number">6</span> msec per loop</span>
</code></pre></div><h4 id="矢量化方法"><a href="#矢量化方法" class="header-anchor">#</a> 矢量化方法</h4> <p>但是我们可以更好地使用Python的itertools模块，该模块提供了<em>一组函数来创建迭代器以实现高效循环</em>。如果我们观察到随机行走是一个步骤的累积，我们可以通过首先生成所有步骤来重写函数，然后在没有任何循环的情况下累加它们：</p> <div class="language-python extra-class"><pre class="language-python"><code><span class="token keyword">def</span> <span class="token function">random_walk_faster</span><span class="token punctuation">(</span>n<span class="token operator">=</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">from</span> itertools <span class="token keyword">import</span> accumulate
    <span class="token comment"># 仅适用于Python3.6</span>
    steps <span class="token operator">=</span> random<span class="token punctuation">.</span>choices<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> k<span class="token operator">=</span>n<span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">+</span><span class="token builtin">list</span><span class="token punctuation">(</span>accumulate<span class="token punctuation">(</span>steps<span class="token punctuation">)</span><span class="token punctuation">)</span>

 walk <span class="token operator">=</span> random_walk_faster<span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span>
</code></pre></div><p>实际上，我们已经将函数<em>向量化</em>了。我们没有循环选择顺序步骤并将其添加到当前位置，而是首先一次生成所有步骤，并使用<code>accumulate</code>函数计算所有位置。我们摆脱了循环，这让事情变得更快：</p> <div class="language-batch extra-class"><pre class="language-batch"><code>&gt;&gt;&gt; from tools import timeit
&gt;&gt;&gt; timeit<span class="token punctuation">(</span>&quot;random_walk_faster<span class="token punctuation">(</span><span class="token command"><span class="token keyword">n</span>=<span class="token number">10000</span></span><span class="token punctuation">)</span>&quot;, globals<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token command"><span class="token keyword">10</span> loops, best of <span class="token number">3</span>: <span class="token number">2</span>.<span class="token number">21</span> msec per loop</span>
</code></pre></div><p>与之前的版本相比，我们获得了85%的计算时间，还不错。但是这个新版本的优点是它使numpy矢量化变得非常简单。我们只需要将itertools调用转换为numpy调用。</p> <div class="language-python extra-class"><pre class="language-python"><code><span class="token keyword">def</span> <span class="token function">random_walk_fastest</span><span class="token punctuation">(</span>n<span class="token operator">=</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token comment"># 在numpy的choice函数中没有‘s’ (Python提供了choice和choices)</span>
    steps <span class="token operator">=</span> np<span class="token punctuation">.</span>random<span class="token punctuation">.</span>choice<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> n<span class="token punctuation">)</span>
    <span class="token keyword">return</span> np<span class="token punctuation">.</span>cumsum<span class="token punctuation">(</span>steps<span class="token punctuation">)</span>

walk <span class="token operator">=</span> random_walk_fastest<span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span>
</code></pre></div><p>不太难，但我们使用numpy将效率提升了500倍：</p> <div class="language-batch extra-class"><pre class="language-batch"><code>&gt;&gt;&gt; from tools import timeit
&gt;&gt;&gt; timeit<span class="token punctuation">(</span>&quot;random_walk_fastest<span class="token punctuation">(</span><span class="token command"><span class="token keyword">n</span>=<span class="token number">10000</span></span><span class="token punctuation">)</span>&quot;, globals<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token command"><span class="token keyword">1000</span> loops, best of <span class="token number">3</span>: <span class="token number">14</span> usec per loop</span>
</code></pre></div><p>这本书是关于向量化的，无论是在代码层面还是在问题层面。在研究自定义矢量化之前，我们将看到这种差异的重要性。</p> <h3 id="可读性vs速度"><a href="#可读性vs速度" class="header-anchor">#</a> 可读性vs速度</h3> <p>在进入下一章之前，我想提醒您，一旦您熟悉了numpy，您可能会遇到一个潜在的问题。它是一个非常强大的库，你可以用它创造奇迹，但是，大多数时候，这是以可读性为代价的。如果您在编写代码时不加注释，那么在几周（或者可能几天）之后，您将无法判断函数在做什么。例如，你能说出下面两个函数在做什么吗？也许你能分辨出第一本书，但不太可能知道第二本书（或者你的名字叫杰米·费尔南德斯·德尔雷奥，你不需要读这本书）。</p> <div class="language-python extra-class"><pre class="language-python"><code><span class="token keyword">def</span> <span class="token function">function_1</span><span class="token punctuation">(</span>seq<span class="token punctuation">,</span> sub<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">return</span> <span class="token punctuation">[</span>i <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>seq<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token builtin">len</span><span class="token punctuation">(</span>sub<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">if</span> seq<span class="token punctuation">[</span>i<span class="token punctuation">:</span>i<span class="token operator">+</span><span class="token builtin">len</span><span class="token punctuation">(</span>sub<span class="token punctuation">)</span><span class="token punctuation">]</span> <span class="token operator">==</span> sub<span class="token punctuation">]</span>

<span class="token keyword">def</span> <span class="token function">function_2</span><span class="token punctuation">(</span>seq<span class="token punctuation">,</span> sub<span class="token punctuation">)</span><span class="token punctuation">:</span>
    target <span class="token operator">=</span> np<span class="token punctuation">.</span>dot<span class="token punctuation">(</span>sub<span class="token punctuation">,</span> sub<span class="token punctuation">)</span>
    candidates <span class="token operator">=</span> np<span class="token punctuation">.</span>where<span class="token punctuation">(</span>np<span class="token punctuation">.</span>correlate<span class="token punctuation">(</span>seq<span class="token punctuation">,</span> sub<span class="token punctuation">,</span> mode<span class="token operator">=</span><span class="token string">'valid'</span><span class="token punctuation">)</span> <span class="token operator">==</span> target<span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>
    check <span class="token operator">=</span> candidates<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> np<span class="token punctuation">.</span>newaxis<span class="token punctuation">]</span> <span class="token operator">+</span> np<span class="token punctuation">.</span>arange<span class="token punctuation">(</span><span class="token builtin">len</span><span class="token punctuation">(</span>sub<span class="token punctuation">)</span><span class="token punctuation">)</span>
    mask <span class="token operator">=</span> np<span class="token punctuation">.</span><span class="token builtin">all</span><span class="token punctuation">(</span><span class="token punctuation">(</span>np<span class="token punctuation">.</span>take<span class="token punctuation">(</span>seq<span class="token punctuation">,</span> check<span class="token punctuation">)</span> <span class="token operator">==</span> sub<span class="token punctuation">)</span><span class="token punctuation">,</span> axis<span class="token operator">=</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span>
    <span class="token keyword">return</span> candidates<span class="token punctuation">[</span>mask<span class="token punctuation">]</span>
</code></pre></div><p>正如您可能已经猜到的，第二个函数是第一个函数的矢量化优化更快的numy版本。它比纯Python版本快10倍，但几乎不可读。</p> <h2 id="数列-array-的剖析"><a href="#数列-array-的剖析" class="header-anchor">#</a> 数列（array）的剖析</h2> <h3 id="介绍"><a href="#介绍" class="header-anchor">#</a> 介绍</h3> <p>正如序言中所解释的，你应该对numpy有一个基本的经验来阅读这本书。如果不是这样的话，你最好在回来之前先从初学者教程开始。因此，我将在这里简要介绍numpy数组的基本结构，特别是关于内存布局、视图、副本和数据类型。如果你想让你的计算受益于numpy哲学，它们是需要理解的关键概念。</p></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">更新于:</span> <span class="time">11/23/2020, 11:07:10 AM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/back-end/koa2.html" class="prev">
        使用 koa2 开发服务端
      </a></span> <span class="next"><a href="/back-end/linux.html">
        linux核心技能
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"><!----></div></div>
    <script src="/assets/js/app.9e067b79.js" defer></script><script src="/assets/js/2.983eb755.js" defer></script><script src="/assets/js/13.de8b1ace.js" defer></script>
  </body>
</html>
